using System;
using System.Collections.Generic;
using UnityEngine;

namespace EntityKit.Runtime
{
    public abstract class Entity : MonoBehaviour, IEntity
    {
        private StateMachine mStateMachine = null;
        private EntityComponentContainer mComponents = null;
        private EventGroup mEventGroup = null;

        [SerializeField] [HideInInspector] private string mEntityID = string.Empty;
        public bool IsInit { get; private set; }
        public string EntityID => mEntityID;

        public virtual void OnInit()
        {
            if (IsInit)
                throw new Exception($"实体已经初始化过了{mEntityID}");
            IsInit = true;
            mComponents = new EntityComponentContainer(this);
            mStateMachine = new StateMachine(this);
            mEventGroup = new EventGroup();
            mComponents.OnInit(this);
        }

        public virtual void OnUpdate()
        {
            if (!IsInit) return;
            mComponents.OnUpdate();
            mStateMachine?.Update();
        }

        public virtual void OnRelease()
        {
            if (!IsInit)
                throw new System.Exception($"不能释放一个没有初始化的实体 {mEntityID}.");
            IsInit = false;
            ReleaseStateMachine();
            mEventGroup.RemoveAllListener();
            mComponents.OnRelease();
            try
            {
                if (gameObject != null && !gameObject.Equals(null))
                    Destroy(this.gameObject);
            }
            catch (Exception e)
            {
#if UNITY_EDITOR
                Debug.LogWarning($"Release Entity failed: {e.Message} StackTrace {e.StackTrace}");
#else
                Debug.LogError($"Release Entity {this.name} failed: {e.Message} StackTrace {e.StackTrace}");
#endif
            }
        }

        public void CollectionComponents()
        {
            mComponents.CollectionComponents();
        }

        /// <summary>
        /// 安全获取实体组件
        /// </summary>
        /// <typeparam name="T">要获取的组件类型</typeparam>
        /// <returns>找到的组件实例，如果不存在则返回null</returns>
        public T GetEntityComponent<T>() where T : class, IEntityComponent
        {
            // 使用TryGet避免异常开销
            if (mComponents.TryGetEntityComponent<T>(out T component))
            {
                return component;
            }

            return null;
        }

        // 添加TryGet方法避免异常开销
        public bool TryGetEntityComponent<T>(out T component) where T : class, IEntityComponent
        {
            return mComponents.TryGetEntityComponent<T>(out component);
        }

        public List<T> GetEntityComponents<T>() where T : class, IEntityComponent
        {
            return mComponents.GetEntityComponents<T>();
        }

        public List<IEntityComponent> GetAllEntityComponents()
        {
            return mComponents.GetAllEntityComponents();
        }

        public void AddEntityComponent(IEntityComponent component)
        {
            mComponents.AddEntityComponent(component);
        }

        public void RemoveEntityComponent(IEntityComponent component)
        {
            mComponents.RemoveEntityComponent(component);
        }

        public bool ContainsEntityComponent<T>() where T : class, IEntityComponent
        {
            return mComponents.Contains<T>();
        }

        /// <summary>
        /// 添加事件监听器
        /// </summary>
        public void AddEventListener<TEvent>(System.Action<IEventMessage> listener) where TEvent : IEventMessage
        {
            mEventGroup.AddListener<TEvent>(listener);
        }

        /// <summary>
        /// 发送事件消息
        /// </summary>
        public void SendEventMessage(IEventMessage message)
        {
            EventKit.SendMessage(message);
        }

        /// <summary>
        /// 延迟发送事件消息
        /// </summary>
        public void PostEventMessage(IEventMessage message)
        {
            EventKit.PostMessage(message);
        }

        /// <summary>
        /// 添加状态节点
        /// </summary>
        public void AddStateNode<TNode>() where TNode : IStateNode, new()
        {
            mStateMachine.AddNode<TNode>();
        }

        /// <summary>
        /// 添加状态转换规则
        /// </summary>
        public void AddStateTransition<TFrom, TTo>() where TFrom : IStateNode where TTo : IStateNode
        {
            mStateMachine.AddTransition<TFrom, TTo>();
        }

        /// <summary>
        /// 切换状态
        /// </summary>
        public void ChangeState<TNode>() where TNode : IStateNode
        {
            mStateMachine.ChangeState<TNode>();
        }

        /// <summary>
        /// 启动状态机
        /// </summary>
        public void RunState<TNode>() where TNode : IStateNode, new()
        {
            mStateMachine.Run<TNode>();
        }

        /// <summary>
        /// 回退到上一个状态
        /// </summary>
        public void RevertToPreviousState()
        {
            mStateMachine.RevertToPrevious();
        }

        /// <summary>
        /// 清空当前状态
        /// </summary>
        public void ClearState()
        {
            mStateMachine.ClearState();
        }

        /// <summary>
        /// 检查当前是否处于指定状态
        /// </summary>
        public bool IsInState<TNode>() where TNode : IStateNode
        {
            return mStateMachine.IsInState<TNode>();
        }

        /// <summary>
        /// 检查之前是否处于指定状态
        /// </summary>
        public bool WasInState<TNode>() where TNode : IStateNode
        {
            return mStateMachine.WasInState<TNode>();
        }

        /// <summary>
        /// 获取当前状态节点
        /// </summary>
        public IStateNode CurrentState => mStateMachine?.CurrentNode;

        /// <summary>
        /// 获取上一个状态节点
        /// </summary>
        public IStateNode PreviousState => mStateMachine?.PreviousNode;

        /// <summary>
        /// 设置黑板数据
        /// </summary>
        public void SetStateData<T>(string key, T value)
        {
            mStateMachine.SetData(key, value);
        }

        /// <summary>
        /// 获取黑板数据
        /// </summary>
        public T GetStateData<T>(string key, T defaultValue = default)
        {
            return mStateMachine.GetData(key, defaultValue);
        }

        /// <summary>
        /// 添加状态切换事件监听
        /// </summary>
        public void AddStateChangeListener(Action<IStateNode, IStateNode> listener)
        {
            mStateMachine.OnStateChanged += listener;
        }

        /// <summary>
        /// 移除状态切换事件监听
        /// </summary>
        public void RemoveStateChangeListener(Action<IStateNode, IStateNode> listener)
        {
            mStateMachine.OnStateChanged -= listener;
        }

        private void ReleaseStateMachine()
        {
            var readOnlyDictionary = mStateMachine.GetAllNodes();
            foreach (var item in readOnlyDictionary)
            {
                var node = item.Value;
                node.OnRelease(node == CurrentState);
            }
        }
    }
}